-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Security solution] Attack discovery tour #182605
Conversation
Pinging @elastic/security-solution (Team: SecuritySolution) |
<h4> | ||
<EuiIcon type="cheer" color="success" /> {i18n.ATTACK_DISCOVERY_TOUR_VIDEO_STEP_TITLE} | ||
</h4> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x-pack/plugins/security_solution/public/attack_discovery/tour/video_toast.tsx
Outdated
Show resolved
Hide resolved
onFocus={handleOnMouseOver} | ||
onBlur={handleOnMouseOut} | ||
> | ||
<iframe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice if we could set the background of the embedded page for dark mode. For the video itself it's transparent
(and seems that way for the body/page), but it's coming through as white, so on dark mode we get these top and bottom white borders. Maybe we can change on the video site, but then would need one link for each theme (light/dark)....
Maybe we can use css/react to dig into the iframe and set the appropriate euiThemeColor
?
CleanShot.2024-05-07.at.13.48.47.mp4
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
going to hold on this til i hear from design if we can use a gif here instead
referrerPolicy="no-referrer" | ||
sandbox="allow-scripts allow-same-origin" | ||
scrolling="no" | ||
// since we cannot go fullscreen, we are autoplaying and removing the controls |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor nit: since we can't go fullscreen, can we disable the fullscreen button? It just toggles and doesn't do anything now once the other tab has been opened, so not a big deal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
going to hold on this til i hear from design if we can use a gif here instead
const VIDEO_CONTENT_HEIGHT = 160; | ||
const VIDEO_CONTENT_WIDTH = 250; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we can't go fullscreen, and you can't really tell what is going on with the video at this size (though you can hear James' beautiful voice), I wonder if we should just show an image capture of the video instead of actually embedding the video and avoid all the useEffect logic.
Alternatively, the whole page should be blank for the user, so could either make the portal bigger or even just use the empty state of the page? That's more discussion with design and there's not much time left so I don't know.
As a user though, I don't find any utility in watching the video in this teeny tiny portal, so would probably just watch it in a new tab.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I asked design and they don't want to make the toast bigger. it would certainly be easier to do the onClick
on a gif vs the hacked iframe solution I have. let me see if that is cool with design
@bojanasan @codearos what do you think about using a gif here instead of the autoplay video?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gif or image... either way, would design be willing to provide a file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Checked out, tested locally, and code changes LGTM!
Made some design nits, and noted a bug where un-muting triggers the 'open in a new tab' behavior, but overall if we're keen on keeping Step 2 of the tour the size it is, I think we should just show a screenshot of the video to avoid all these issues since we can't fullscreen at the moment.
Code looks good though, and I appreciate the tests + follow-up issue to disable this in 8.16
, so I think we just need to check with design and see what they think. Thanks @stephmilovic!
@elasticmachine merge upstream |
Hi @stephmilovic, the implementation looks good. However, this approach won't work with the new side nav (here's our PR adapting to it #179971), it is still in "internal preview" stage so I guess it is not strictly necessary. But this won't work in the serverless nav either (it uses the same shared-ux component), actually, I tested that in serverless and I don't even see the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@elasticmachine merge upstream |
💚 Build Succeeded
Metrics [docs]Module Count
Public APIs missing comments
Async chunks
Page load bundle
Unknown metric groupsAPI count
miscellaneous assets size
History
To update your PR or re-run it, just comment with: |
(cherry picked from commit ef0bd2e)
💚 All backports created successfully
Note: Successful backport PRs will be merged automatically after passing CI. Questions ?Please refer to the Backport tool documentation |
# Backport This will backport the following commits from `main` to `8.14`: - [[Security solution] Attack discovery tour (#182605)](#182605) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Steph Milovic","email":"stephanie.milovic@elastic.co"},"sourceCommit":{"committedDate":"2024-05-08T20:16:54Z","message":"[Security solution] Attack discovery tour (#182605)","sha":"ef0bd2e23146a3a8242be451540a7cad34c9b605","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team: SecuritySolution","ci:cloud-deploy","Team:Security Generative AI","v8.14.0","v8.15.0","Feature:Attack Discovery"],"title":"[Security solution] Attack discovery tour","number":182605,"url":"https://github.com/elastic/kibana/pull/182605","mergeCommit":{"message":"[Security solution] Attack discovery tour (#182605)","sha":"ef0bd2e23146a3a8242be451540a7cad34c9b605"}},"sourceBranch":"main","suggestedTargetBranches":["8.14"],"targetPullRequestStates":[{"branch":"8.14","label":"v8.14.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.15.0","branchLabelMappingKey":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/182605","number":182605,"mergeCommit":{"message":"[Security solution] Attack discovery tour (#182605)","sha":"ef0bd2e23146a3a8242be451540a7cad34c9b605"}}]}] BACKPORT--> Co-authored-by: Steph Milovic <stephanie.milovic@elastic.co>
…play an upgrade CTA for the serverless essentials product tier ### Summary This PR adds Role Based Access Control (RBAC) to Attack discovery. Security users may enable or disable the new `Attack Discovery` RBAC feature shown in the figure below: ![rbac](https://github.com/user-attachments/assets/2ca3de6e-3e87-401f-8a06-0eb06d36d081) _Above: The new `Attack discovery` RBAC feature_ It is possible to for example, configure a custom role that enables Attack discovery, but disables the assistant, as illustrated by the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_none` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Trial | ✅ | ❌ | ❌ | ❌ | | `has_attack_discovery_all_assistant_none` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Enterprise | ✅ | ❌ | ❌ | ❌ | _Above: An example role that enables Attack discovery, but disables the assistant_ See the `Desk Testing` section of this PR for details. This PR also fixes an issue where Attack discovery does not display an upgrade call to action (CTA) for the serverless _essentials_ product tier, per the before and after screenshots below: #### Before ![serverless_essentials_before](https://github.com/user-attachments/assets/90e8f433-896d-40a3-b095-8f0cca0f7073) _Above: Before the fix, an upgrade CTA is NOT displayed for the serverless essentials product tier_ #### After ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) _Above: After the fix, an upgrade CTA is displayed for the serverless essentials product tier_ The fix above is implemented by adopting the upselling framework. ### New Feature ID This PR adds a new Feature ID for attack discovery: ```typescript export const ATTACK_DISCOVERY_FEATURE_ID = 'securitySolutionAttackDiscovery' as const; ``` in `x-pack/packages/security-solution/features/src/constants.ts` ### Upselling framework usage This PR updates the Attack discovery page to use the upselling framework via the following summarized steps: 1. Removed the branching logic from `x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.tsx`, and moved the component to an upselling `section` component in `x-pack/packages/security-solution/upselling/sections/attack_discovery/index.tsx`, where the component was renamed to `AttackDiscoveryUpsellingSection`. This `section` component handles (just) the styling of the upselling message and actions (by itself, without the page wrapper), and receives the following props: ```typescript interface Props { actions?: React.ReactNode; availabilityMessage: string; upgradeMessage: string; } ``` The self managed and serverless-specific actions and `i18n` messages are passed down via the components described in the later steps below. 2. Removed all previous references to the `Upgrade` component (and references to `useProductTypes`) from the Attack discovery page in `x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx`, because the framework manages the upgrade case instead of the page itself. 3. Created an upselling `page` component `AttackDiscoveryUpsellingPage` in `x-pack/packages/security-solution/upselling/pages/attack_discovery/index.tsx`. This component handles (just) the styling of the _page_ that wraps the Attack discovery `section`. It passes the same props to the previously described `AttackDiscoveryUpsellingSection` component. 4. Created a self-managed-specific `AttackDiscoveryUpsellingPageESS` component in `x-pack/plugins/security_solution_ess/public/upselling/pages/attack_discovery/index.tsx` This component passes self-managed-specific upgrade action buttons / links and `i18n` strings to the previously described `AttackDiscoveryUpsellingPage` 5. Also for self managed, added a new `AttackDiscoveryUpsellingPageLazy` component to the existing file: `x-pack/plugins/security_solution_ess/public/upselling/lazy_upselling.tsx` This component lazy loads the previously described `AttackDiscoveryUpsellingPageESS` component. 6. Added registration for the previously described `AttackDiscoveryUpsellingPageLazy` component to the existing `UpsellingPages` section in `x-pack/plugins/security_solution_ess/public/upselling/register_upsellings.tsx` with a `minimumLicenseRequired` of `enterprise`: ``` minimumLicenseRequired: 'enterprise', ``` 7. Created a serverless-specific `AttackDiscoveryUpsellingPageServerless` component in `x-pack/plugins/security_solution_serverless/public/upselling/pages/attack_discovery/index.tsx` This component passes serverless-specific `i18n` messages to the platform agnostic `AttackDiscoveryUpsellingPage` component. 8. Also for serverless, added a new `AttackDiscoveryUpsellingPageLazy` component to the existing file: `x-pack/plugins/security_solution_serverless/public/upselling/lazy_upselling.tsx` 9. Added registration for the previously described `AttackDiscoveryUpsellingPageLazy` component to the existing `upsellingPages` section in `x-pack/plugins/security_solution_serverless/public/upselling/upsellings.tsx` with the `assistant` PLI: ``` pli: ProductFeatureKey.assistant, ``` 10. Added the `${ASSISTANT_FEATURE_ID}.ai-assistant` capability as an OR condition (via nested array, per the [framework](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/common/lib/capabilities/has_capabilities.ts#L11-L22)) to the Attack discovery link in `x-pack/plugins/security_solution/public/attack_discovery/links.ts`. This addition enables the security route wrapper to check for upselling pages in serverless: ``` capabilities: [[`${SERVER_APP_ID}.show`, `${ASSISTANT_FEATURE_ID}.ai-assistant`]], ``` 11. Added `licenseType: 'enterprise'` to the Attack discovery link in `x-pack/plugins/security_solution/public/attack_discovery/links.ts` to require an `enterprise` license for self managed ### Upgrade CTA gallery The screenshots in this section document the CTA (or Welcome message when the feature is licensed) displayed for various license levels after the fix: #### Users with the `None` privilege If users with the `None` privilege manually enter an Attack discovery URL, e.g. `http://localhost:5601/app/security/attack_discovery`, the framework will display the following error prompt: ![privelages_required](https://github.com/user-attachments/assets/d282609e-5400-4ba9-8130-de5e10f8973d) #### Self managed BASIC ![self_managed_basic_after](https://github.com/user-attachments/assets/048b2a3b-9e2d-4b95-a697-c739ea2dc5bb) #### Self managed PLATINUM ![self_managed_platinum_after](https://github.com/user-attachments/assets/d7c49551-a8cf-4afb-b3bf-c3243e892219) #### Self managed TRIAL ![self_managed_trial_after](https://github.com/user-attachments/assets/d5cc03a9-97aa-4c78-a5f5-92e5af3a85ac) #### Self managed ENTERPRISE ![self_managed_enterprise_after](https://github.com/user-attachments/assets/a849b534-7e07-4481-9641-c48dee126466) #### Serverless ESSENTIALS ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) #### Serverless COMPLETE ![serverless_complete_after](https://github.com/user-attachments/assets/8cab60c3-dea6-4d7a-b86a-b2cd11c9b4dd) ## Desk Testing ### Severless: Desk testing (just) the upgrade CTA Reproduction steps: 1) Comment-out any preconfigured connectors in `config/kibana.dev.yml` 2) Edit the configuration of `config/serverless.security.yml` to enable the `essentials` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' } ] ``` 3) Start Elasticsearch ```sh yarn es serverless --projectType security ``` 4) Start a development instance of Kibana ``` yarn start --serverless=security --no-base-path ``` 5) Navigate to Security > Attack discovery **Expected result** - An upgrade CTA is displayed, as illustrated by the _after_ screenshot below: ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) - The video tour is NOT displayed for serverless, as noted in the [original PR](elastic#182605 (comment)) **Actual result** - An upgrade CTA is NOT displayed, as illustrated by the _before_ screenshot below: ![serverless_essentials_before](https://github.com/user-attachments/assets/90e8f433-896d-40a3-b095-8f0cca0f7073) ### Desk testing Self Managed To desk test self manged, we will: 1) Create (three) roles for testing 2) Create (three) users assigned to the roles 3) Test each role at `Basic`, `Trial`, `Platinum`, and `Enterprise` levels to verify: - `Attack discovery` link visibility in the Security solution navigation - Visibility of the upsell empty prompt for license levels where Attack discovery is unavailable - The upsell empty prompt includes the `Subscription plans` and `Manage license` actions - When Attack discoveries are generated, the `View in Ai Assistant` button and popover menu action are enabled / disabled, based on availability of the `AI Assistant` feature #### Creating (three) roles for testing In this section, we will start a new (development) self managed deployment, and create the following three roles via Kibana Dev Tools: - `has_attack_discovery_all_assistant_all` - `has_attack_discovery_all_assistant_none` - `has_attack_discovery_none_assistant_all` To start the deployment and create the roles: 1) Add a pre-configured GenAI connector to `config/kibana.dev.yml` 2) Start a new (development) instance of Elasticsearch: ```sh yarn es snapshot -E path.data=/Users/$USERNAME/data-2024-07-31a ``` 3) Start a local (development) instance of Kibana: ``` yarn start --no-base-path ```` 4) Login to Kibana as the `elastic` user 5) Generate some alerts 6) Navigate to Dev Tools 7) Execute the following three API calls to create the roles: <details><summary>PUT /_security/role/has_attack_discovery_all_assistant_all</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_all_assistant_all { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAssistant.minimal_all", "feature_securitySolutionAttackDiscovery.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> <details><summary>PUT /_security/role/has_attack_discovery_all_assistant_none</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_all_assistant_none { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAttackDiscovery.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> <details><summary>PUT /_security/role/has_attack_discovery_none_assistant_all</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_none_assistant_all { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAssistant.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> #### Creating (three) users assigned to the roles In this section, we will create the following three users via Kibana Dev Tools using the API calls below (expand for details): - `attack_discovery_all_assistant_all` - `attack_discovery_all_assistant_none` - `attack_discovery_none_assistant_all` 1) Navigate to Dev Tools 2) Execute the following three API calls to create the users: <details><summary>POST /_security/user/attack_discovery_all_assistant_all</summary> <p> ``` ts POST /_security/user/attack_discovery_all_assistant_all { "username": "attack_discovery_all_assistant_all", "password": "changeme", "roles": [ "has_attack_discovery_all_assistant_all" ], "full_name": "Attack Discovery All Assistant All", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> <details><summary>POST /_security/user/attack_discovery_all_assistant_none</summary> <p> ``` ts POST /_security/user/attack_discovery_all_assistant_none { "username": "attack_discovery_all_assistant_none", "password": "changeme", "roles": [ "has_attack_discovery_all_assistant_none" ], "full_name": "Attack Discovery All Assistant None", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> <details><summary>POST /_security/user/attack_discovery_none_assistant_all</summary> <p> ``` ts POST /_security/user/attack_discovery_none_assistant_all { "username": "attack_discovery_none_assistant_all", "password": "changeme", "roles": [ "has_attack_discovery_none_assistant_all" ], "full_name": "Attack Discovery None Assistant All", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> #### Testing each role at `Basic`, `Trial`, `Platinum`, and `Enterprise` levels In this section, we will test each of the self managed `Basic`, `Trial`, `Platinum`, and `Enterprise` license levels with the three roles we created for testing. ##### Testing the `has_attack_discovery_all_assistant_all` role 1) Login as the `attack_discovery_all_assistant_all` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_all` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_all` | Trial | ✅ | ❌ | ❌ | ✅ | | `has_attack_discovery_all_assistant_all` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_all` | Enterprise | ✅ | ❌ | ❌ | ✅ | ##### Testing the `has_attack_discovery_all_assistant_none` role 1) Login as the `attack_discovery_all_assistant_none` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_none` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Trial | ✅ | ❌ | ❌ | ❌ | | `has_attack_discovery_all_assistant_none` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Enterprise | ✅ | ❌ | ❌ | ❌ | ##### Testing the `has_attack_discovery_none_assistant_all` role 1) Login as the `attack_discovery_none_assistant_all` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_none_assistant_all` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_none_assistant_all` | Trial | ❌ | ❌ | ❌ | ❌ | | `has_attack_discovery_none_assistant_all` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_none_assistant_all` | Enterprise | ❌ | ❌ | ❌ | ❌ | --------------------------------------------- ### Serverless Testing To desk test serverless, we will test the `essentials` and `complete` product tiers to verify: - `Attack discovery` link visibility in the Security project navigation - Visibility of the upsell empty prompt for license levels where Attack discovery is unavailable - The upsell empty prompt does NOT include the `Subscription plans` and `Manage license` actions - When Attack discoveries are generated, the `View in Ai Assistant` button and popover menu action are enabled #### Essentials tier testing 1) Add a pre-configured GenAI connector to `config/kibana.dev.yml` 2) Edit the configuration of `config/serverless.security.yml` to enable the `essentials` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' }, { product_line: 'endpoint', product_tier: 'essentials' }, ] ``` 2) Start a new (development) instance of Elasticsearch: ```sh yarn es serverless --clean --projectType security ``` 3) Start a local (development) instance of Kibana: ``` yarn start --serverless=security --no-base-path ```` 4) select the `admin` role 5) Generate some alerts 6) Verify your observations match the expected behavior in the table below: | Role | Tier | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `viewer` | essentials | ✅ | ✅ | ❌ | ❌ | | `editor` | essentials | ✅ | ✅ | ❌ | ❌ | | `t1_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `t2_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `t3_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `threat_intelligence_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `rule_author` | essentials | ✅ | ✅ | ❌ | ❌ | | `soc_manager` | essentials | ✅ | ✅ | ❌ | ❌ | | `detections_admin` | essentials | ✅ | ✅ | ❌ | ❌ | | `platform_engineer` | essentials | ✅ | ✅ | ❌ | ❌ | | `endpoint_operations_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `endpoint_policy_manager` | essentials | ✅ | ✅ | ❌ | ❌ | | `admin` | essentials | ✅ | ✅ | ❌ | ❌ | | `system_indices_superuser` | essentials | ✅ | ✅ | ❌ | ❌ | ### Complete tier testing 1) Stop the running Kibana server (from the previous Essentials tier testing) 2) Edit the configuration of `config/serverless.security.yml` to enable the `complete` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, ] ``` 3) Restart a local (development) instance of Kibana: ``` yarn start --serverless=security --no-base-path ```` 4) Verify your observations match the expected behavior in the table below: | Role | Tier | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------|----------|--------------------|-------------|--------------------|---------------------------| | `viewer` | complete | ✅ | ❌ | ❌ | ✅ | | `editor` | complete | ✅ | ❌ | ❌ | ✅ | | `t1_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `t2_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `t3_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `threat_intelligence_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `rule_author` | complete | ✅ | ❌ | ❌ | ✅ | | `soc_manager` | complete | ✅ | ❌ | ❌ | ✅ | | `detections_admin` | complete | ✅ | ❌ | ❌ | ✅ | | `platform_engineer` | complete | ✅ | ❌ | ❌ | ✅ | | `endpoint_operations_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `endpoint_policy_manager` | complete | ✅ | ❌ | ❌ | ✅ | | `admin` | complete | ✅ | ❌ | ❌ | ✅ | | `system_indices_superuser` | complete | ✅ | ❌ | ❌ | ✅ |
…y an upgrade CTA for the serverless essentials product tier (#188788) ## [Security Solution] [Attack discovery] Attack Discovery RBAC / Display an upgrade CTA for the serverless essentials product tier ### Summary This PR adds Role Based Access Control (RBAC) to Attack discovery. Security users may enable or disable the new `Attack Discovery` RBAC feature shown in the figure below: ![rbac](https://github.com/user-attachments/assets/2ca3de6e-3e87-401f-8a06-0eb06d36d081) _Above: The new `Attack discovery` RBAC feature_ It is possible to for example, configure a custom role that enables Attack discovery, but disables the assistant, as illustrated by the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_none` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Trial | ✅ | ❌ | ❌ | ❌ | | `has_attack_discovery_all_assistant_none` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Enterprise | ✅ | ❌ | ❌ | ❌ | _Above: An example role that enables Attack discovery, but disables the assistant_ See the `Desk Testing` section of this PR for details. This PR also fixes an issue where Attack discovery does not display an upgrade call to action (CTA) for the serverless _essentials_ product tier, per the before and after screenshots below: #### Before ![serverless_essentials_before](https://github.com/user-attachments/assets/90e8f433-896d-40a3-b095-8f0cca0f7073) _Above: Before the fix, an upgrade CTA is NOT displayed for the serverless essentials product tier_ #### After ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) _Above: After the fix, an upgrade CTA is displayed for the serverless essentials product tier_ The fix above is implemented by adopting the upselling framework. ### New Feature ID This PR adds a new Feature ID for attack discovery: ```typescript export const ATTACK_DISCOVERY_FEATURE_ID = 'securitySolutionAttackDiscovery' as const; ``` in `x-pack/packages/security-solution/features/src/constants.ts` ### Upselling framework usage This PR updates the Attack discovery page to use the upselling framework via the following summarized steps: 1. Removed the branching logic from `x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.tsx`, and moved the component to an upselling `section` component in `x-pack/packages/security-solution/upselling/sections/attack_discovery/index.tsx`, where the component was renamed to `AttackDiscoveryUpsellingSection`. This `section` component handles (just) the styling of the upselling message and actions (by itself, without the page wrapper), and receives the following props: ```typescript interface Props { actions?: React.ReactNode; availabilityMessage: string; upgradeMessage: string; } ``` The self managed and serverless-specific actions and `i18n` messages are passed down via the components described in the later steps below. 2. Removed all previous references to the `Upgrade` component (and references to `useProductTypes`) from the Attack discovery page in `x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx`, because the framework manages the upgrade case instead of the page itself. 3. Created an upselling `page` component `AttackDiscoveryUpsellingPage` in `x-pack/packages/security-solution/upselling/pages/attack_discovery/index.tsx`. This component handles (just) the styling of the _page_ that wraps the Attack discovery `section`. It passes the same props to the previously described `AttackDiscoveryUpsellingSection` component. 4. Created a self-managed-specific `AttackDiscoveryUpsellingPageESS` component in `x-pack/plugins/security_solution_ess/public/upselling/pages/attack_discovery/index.tsx` This component passes self-managed-specific upgrade action buttons / links and `i18n` strings to the previously described `AttackDiscoveryUpsellingPage` 5. Also for self managed, added a new `AttackDiscoveryUpsellingPageLazy` component to the existing file: `x-pack/plugins/security_solution_ess/public/upselling/lazy_upselling.tsx` This component lazy loads the previously described `AttackDiscoveryUpsellingPageESS` component. 6. Added registration for the previously described `AttackDiscoveryUpsellingPageLazy` component to the existing `UpsellingPages` section in `x-pack/plugins/security_solution_ess/public/upselling/register_upsellings.tsx` with a `minimumLicenseRequired` of `enterprise`: ``` minimumLicenseRequired: 'enterprise', ``` 7. Created a serverless-specific `AttackDiscoveryUpsellingPageServerless` component in `x-pack/plugins/security_solution_serverless/public/upselling/pages/attack_discovery/index.tsx` This component passes serverless-specific `i18n` messages to the platform agnostic `AttackDiscoveryUpsellingPage` component. 8. Also for serverless, added a new `AttackDiscoveryUpsellingPageLazy` component to the existing file: `x-pack/plugins/security_solution_serverless/public/upselling/lazy_upselling.tsx` 9. Added registration for the previously described `AttackDiscoveryUpsellingPageLazy` component to the existing `upsellingPages` section in `x-pack/plugins/security_solution_serverless/public/upselling/upsellings.tsx` with the `assistant` PLI: ``` pli: ProductFeatureKey.assistant, ``` 10. Added the `${ASSISTANT_FEATURE_ID}.ai-assistant` capability as an OR condition (via nested array, per the [framework](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/common/lib/capabilities/has_capabilities.ts#L11-L22)) to the Attack discovery link in `x-pack/plugins/security_solution/public/attack_discovery/links.ts`. This addition enables the security route wrapper to check for upselling pages in serverless: ``` capabilities: [[`${SERVER_APP_ID}.show`, `${ASSISTANT_FEATURE_ID}.ai-assistant`]], ``` 11. Added `licenseType: 'enterprise'` to the Attack discovery link in `x-pack/plugins/security_solution/public/attack_discovery/links.ts` to require an `enterprise` license for self managed ### Upgrade CTA gallery The screenshots in this section document the CTA (or Welcome message when the feature is licensed) displayed for various license levels after the fix: #### Users with the `None` privilege If users with the `None` privilege manually enter an Attack discovery URL, e.g. `http://localhost:5601/app/security/attack_discovery`, the framework will display the following error prompt: ![privelages_required](https://github.com/user-attachments/assets/d282609e-5400-4ba9-8130-de5e10f8973d) #### Self managed BASIC ![self_managed_basic_after](https://github.com/user-attachments/assets/048b2a3b-9e2d-4b95-a697-c739ea2dc5bb) #### Self managed PLATINUM ![self_managed_platinum_after](https://github.com/user-attachments/assets/d7c49551-a8cf-4afb-b3bf-c3243e892219) #### Self managed TRIAL ![self_managed_trial_after](https://github.com/user-attachments/assets/d5cc03a9-97aa-4c78-a5f5-92e5af3a85ac) #### Self managed ENTERPRISE ![self_managed_enterprise_after](https://github.com/user-attachments/assets/a849b534-7e07-4481-9641-c48dee126466) #### Serverless ESSENTIALS ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) #### Serverless COMPLETE ![serverless_complete_after](https://github.com/user-attachments/assets/8cab60c3-dea6-4d7a-b86a-b2cd11c9b4dd) ## Desk Testing ### Severless: Desk testing (just) the upgrade CTA Reproduction steps: 1) Comment-out any preconfigured connectors in `config/kibana.dev.yml` 2) Edit the configuration of `config/serverless.security.yml` to enable the `essentials` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' } ] ``` 3) Start Elasticsearch ```sh yarn es serverless --projectType security ``` 4) Start a development instance of Kibana ``` yarn start --serverless=security --no-base-path ``` 5) Navigate to Security > Attack discovery **Expected result** - An upgrade CTA is displayed, as illustrated by the _after_ screenshot below: ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) - The video tour is NOT displayed for serverless, as noted in the [original PR](#182605 (comment)) **Actual result** - An upgrade CTA is NOT displayed, as illustrated by the _before_ screenshot below: ![serverless_essentials_before](https://github.com/user-attachments/assets/90e8f433-896d-40a3-b095-8f0cca0f7073) ### Desk testing Self Managed To desk test self manged, we will: 1) Create (three) roles for testing 2) Create (three) users assigned to the roles 3) Test each role at `Basic`, `Trial`, `Platinum`, and `Enterprise` levels to verify: - `Attack discovery` link visibility in the Security solution navigation - Visibility of the upsell empty prompt for license levels where Attack discovery is unavailable - The upsell empty prompt includes the `Subscription plans` and `Manage license` actions - When Attack discoveries are generated, the `View in Ai Assistant` button and popover menu action are enabled / disabled, based on availability of the `AI Assistant` feature #### Creating (three) roles for testing In this section, we will start a new (development) self managed deployment, and create the following three roles via Kibana Dev Tools: - `has_attack_discovery_all_assistant_all` - `has_attack_discovery_all_assistant_none` - `has_attack_discovery_none_assistant_all` To start the deployment and create the roles: 1) Add a pre-configured GenAI connector to `config/kibana.dev.yml` 2) Start a new (development) instance of Elasticsearch: ```sh yarn es snapshot -E path.data=/Users/$USERNAME/data-2024-07-31a ``` 3) Start a local (development) instance of Kibana: ``` yarn start --no-base-path ```` 4) Login to Kibana as the `elastic` user 5) Generate some alerts 6) Navigate to Dev Tools 7) Execute the following three API calls to create the roles: <details><summary>PUT /_security/role/has_attack_discovery_all_assistant_all</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_all_assistant_all { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAssistant.minimal_all", "feature_securitySolutionAttackDiscovery.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> <details><summary>PUT /_security/role/has_attack_discovery_all_assistant_none</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_all_assistant_none { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAttackDiscovery.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> <details><summary>PUT /_security/role/has_attack_discovery_none_assistant_all</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_none_assistant_all { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAssistant.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> #### Creating (three) users assigned to the roles In this section, we will create the following three users via Kibana Dev Tools using the API calls below (expand for details): - `attack_discovery_all_assistant_all` - `attack_discovery_all_assistant_none` - `attack_discovery_none_assistant_all` 1) Navigate to Dev Tools 2) Execute the following three API calls to create the users: <details><summary>POST /_security/user/attack_discovery_all_assistant_all</summary> <p> ``` ts POST /_security/user/attack_discovery_all_assistant_all { "username": "attack_discovery_all_assistant_all", "password": "changeme", "roles": [ "has_attack_discovery_all_assistant_all" ], "full_name": "Attack Discovery All Assistant All", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> <details><summary>POST /_security/user/attack_discovery_all_assistant_none</summary> <p> ``` ts POST /_security/user/attack_discovery_all_assistant_none { "username": "attack_discovery_all_assistant_none", "password": "changeme", "roles": [ "has_attack_discovery_all_assistant_none" ], "full_name": "Attack Discovery All Assistant None", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> <details><summary>POST /_security/user/attack_discovery_none_assistant_all</summary> <p> ``` ts POST /_security/user/attack_discovery_none_assistant_all { "username": "attack_discovery_none_assistant_all", "password": "changeme", "roles": [ "has_attack_discovery_none_assistant_all" ], "full_name": "Attack Discovery None Assistant All", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> #### Testing each role at `Basic`, `Trial`, `Platinum`, and `Enterprise` levels In this section, we will test each of the self managed `Basic`, `Trial`, `Platinum`, and `Enterprise` license levels with the three roles we created for testing. ##### Testing the `has_attack_discovery_all_assistant_all` role 1) Login as the `attack_discovery_all_assistant_all` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_all` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_all` | Trial | ✅ | ❌ | ❌ | ✅ | | `has_attack_discovery_all_assistant_all` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_all` | Enterprise | ✅ | ❌ | ❌ | ✅ | ##### Testing the `has_attack_discovery_all_assistant_none` role 1) Login as the `attack_discovery_all_assistant_none` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_none` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Trial | ✅ | ❌ | ❌ | ❌ | | `has_attack_discovery_all_assistant_none` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Enterprise | ✅ | ❌ | ❌ | ❌ | ##### Testing the `has_attack_discovery_none_assistant_all` role 1) Login as the `attack_discovery_none_assistant_all` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_none_assistant_all` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_none_assistant_all` | Trial | ❌ | ❌ | ❌ | ❌ | | `has_attack_discovery_none_assistant_all` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_none_assistant_all` | Enterprise | ❌ | ❌ | ❌ | ❌ | --------------------------------------------- ### Serverless Testing To desk test serverless, we will test the `essentials` and `complete` product tiers to verify: - `Attack discovery` link visibility in the Security project navigation - Visibility of the upsell empty prompt for license levels where Attack discovery is unavailable - The upsell empty prompt does NOT include the `Subscription plans` and `Manage license` actions - When Attack discoveries are generated, the `View in Ai Assistant` button and popover menu action are enabled #### Essentials tier testing 1) Add a pre-configured GenAI connector to `config/kibana.dev.yml` 2) Edit the configuration of `config/serverless.security.yml` to enable the `essentials` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' }, { product_line: 'endpoint', product_tier: 'essentials' }, ] ``` 2) Start a new (development) instance of Elasticsearch: ```sh yarn es serverless --clean --projectType security ``` 3) Start a local (development) instance of Kibana: ``` yarn start --serverless=security --no-base-path ```` 4) select the `admin` role 5) Generate some alerts 6) Verify your observations match the expected behavior in the table below: | Role | Tier | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `viewer` | essentials | ✅ | ✅ | ❌ | ❌ | | `editor` | essentials | ✅ | ✅ | ❌ | ❌ | | `t1_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `t2_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `t3_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `threat_intelligence_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `rule_author` | essentials | ✅ | ✅ | ❌ | ❌ | | `soc_manager` | essentials | ✅ | ✅ | ❌ | ❌ | | `detections_admin` | essentials | ✅ | ✅ | ❌ | ❌ | | `platform_engineer` | essentials | ✅ | ✅ | ❌ | ❌ | | `endpoint_operations_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `endpoint_policy_manager` | essentials | ✅ | ✅ | ❌ | ❌ | | `admin` | essentials | ✅ | ✅ | ❌ | ❌ | | `system_indices_superuser` | essentials | ✅ | ✅ | ❌ | ❌ | ### Complete tier testing 1) Stop the running Kibana server (from the previous Essentials tier testing) 2) Edit the configuration of `config/serverless.security.yml` to enable the `complete` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, ] ``` 3) Restart a local (development) instance of Kibana: ``` yarn start --serverless=security --no-base-path ```` 4) Verify your observations match the expected behavior in the table below: | Role | Tier | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------|----------|--------------------|-------------|--------------------|---------------------------| | `viewer` | complete | ✅ | ❌ | ❌ | ✅ | | `editor` | complete | ✅ | ❌ | ❌ | ✅ | | `t1_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `t2_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `t3_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `threat_intelligence_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `rule_author` | complete | ✅ | ❌ | ❌ | ✅ | | `soc_manager` | complete | ✅ | ❌ | ❌ | ✅ | | `detections_admin` | complete | ✅ | ❌ | ❌ | ✅ | | `platform_engineer` | complete | ✅ | ❌ | ❌ | ✅ | | `endpoint_operations_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `endpoint_policy_manager` | complete | ✅ | ❌ | ❌ | ✅ | | `admin` | complete | ✅ | ❌ | ❌ | ✅ | | `system_indices_superuser` | complete | ✅ | ❌ | ❌ | ✅ |
…y an upgrade CTA for the serverless essentials product tier (elastic#188788) ## [Security Solution] [Attack discovery] Attack Discovery RBAC / Display an upgrade CTA for the serverless essentials product tier ### Summary This PR adds Role Based Access Control (RBAC) to Attack discovery. Security users may enable or disable the new `Attack Discovery` RBAC feature shown in the figure below: ![rbac](https://github.com/user-attachments/assets/2ca3de6e-3e87-401f-8a06-0eb06d36d081) _Above: The new `Attack discovery` RBAC feature_ It is possible to for example, configure a custom role that enables Attack discovery, but disables the assistant, as illustrated by the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_none` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Trial | ✅ | ❌ | ❌ | ❌ | | `has_attack_discovery_all_assistant_none` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Enterprise | ✅ | ❌ | ❌ | ❌ | _Above: An example role that enables Attack discovery, but disables the assistant_ See the `Desk Testing` section of this PR for details. This PR also fixes an issue where Attack discovery does not display an upgrade call to action (CTA) for the serverless _essentials_ product tier, per the before and after screenshots below: #### Before ![serverless_essentials_before](https://github.com/user-attachments/assets/90e8f433-896d-40a3-b095-8f0cca0f7073) _Above: Before the fix, an upgrade CTA is NOT displayed for the serverless essentials product tier_ #### After ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) _Above: After the fix, an upgrade CTA is displayed for the serverless essentials product tier_ The fix above is implemented by adopting the upselling framework. ### New Feature ID This PR adds a new Feature ID for attack discovery: ```typescript export const ATTACK_DISCOVERY_FEATURE_ID = 'securitySolutionAttackDiscovery' as const; ``` in `x-pack/packages/security-solution/features/src/constants.ts` ### Upselling framework usage This PR updates the Attack discovery page to use the upselling framework via the following summarized steps: 1. Removed the branching logic from `x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.tsx`, and moved the component to an upselling `section` component in `x-pack/packages/security-solution/upselling/sections/attack_discovery/index.tsx`, where the component was renamed to `AttackDiscoveryUpsellingSection`. This `section` component handles (just) the styling of the upselling message and actions (by itself, without the page wrapper), and receives the following props: ```typescript interface Props { actions?: React.ReactNode; availabilityMessage: string; upgradeMessage: string; } ``` The self managed and serverless-specific actions and `i18n` messages are passed down via the components described in the later steps below. 2. Removed all previous references to the `Upgrade` component (and references to `useProductTypes`) from the Attack discovery page in `x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx`, because the framework manages the upgrade case instead of the page itself. 3. Created an upselling `page` component `AttackDiscoveryUpsellingPage` in `x-pack/packages/security-solution/upselling/pages/attack_discovery/index.tsx`. This component handles (just) the styling of the _page_ that wraps the Attack discovery `section`. It passes the same props to the previously described `AttackDiscoveryUpsellingSection` component. 4. Created a self-managed-specific `AttackDiscoveryUpsellingPageESS` component in `x-pack/plugins/security_solution_ess/public/upselling/pages/attack_discovery/index.tsx` This component passes self-managed-specific upgrade action buttons / links and `i18n` strings to the previously described `AttackDiscoveryUpsellingPage` 5. Also for self managed, added a new `AttackDiscoveryUpsellingPageLazy` component to the existing file: `x-pack/plugins/security_solution_ess/public/upselling/lazy_upselling.tsx` This component lazy loads the previously described `AttackDiscoveryUpsellingPageESS` component. 6. Added registration for the previously described `AttackDiscoveryUpsellingPageLazy` component to the existing `UpsellingPages` section in `x-pack/plugins/security_solution_ess/public/upselling/register_upsellings.tsx` with a `minimumLicenseRequired` of `enterprise`: ``` minimumLicenseRequired: 'enterprise', ``` 7. Created a serverless-specific `AttackDiscoveryUpsellingPageServerless` component in `x-pack/plugins/security_solution_serverless/public/upselling/pages/attack_discovery/index.tsx` This component passes serverless-specific `i18n` messages to the platform agnostic `AttackDiscoveryUpsellingPage` component. 8. Also for serverless, added a new `AttackDiscoveryUpsellingPageLazy` component to the existing file: `x-pack/plugins/security_solution_serverless/public/upselling/lazy_upselling.tsx` 9. Added registration for the previously described `AttackDiscoveryUpsellingPageLazy` component to the existing `upsellingPages` section in `x-pack/plugins/security_solution_serverless/public/upselling/upsellings.tsx` with the `assistant` PLI: ``` pli: ProductFeatureKey.assistant, ``` 10. Added the `${ASSISTANT_FEATURE_ID}.ai-assistant` capability as an OR condition (via nested array, per the [framework](https://github.com/elastic/kibana/blob/main/x-pack/plugins/security_solution/public/common/lib/capabilities/has_capabilities.ts#L11-L22)) to the Attack discovery link in `x-pack/plugins/security_solution/public/attack_discovery/links.ts`. This addition enables the security route wrapper to check for upselling pages in serverless: ``` capabilities: [[`${SERVER_APP_ID}.show`, `${ASSISTANT_FEATURE_ID}.ai-assistant`]], ``` 11. Added `licenseType: 'enterprise'` to the Attack discovery link in `x-pack/plugins/security_solution/public/attack_discovery/links.ts` to require an `enterprise` license for self managed ### Upgrade CTA gallery The screenshots in this section document the CTA (or Welcome message when the feature is licensed) displayed for various license levels after the fix: #### Users with the `None` privilege If users with the `None` privilege manually enter an Attack discovery URL, e.g. `http://localhost:5601/app/security/attack_discovery`, the framework will display the following error prompt: ![privelages_required](https://github.com/user-attachments/assets/d282609e-5400-4ba9-8130-de5e10f8973d) #### Self managed BASIC ![self_managed_basic_after](https://github.com/user-attachments/assets/048b2a3b-9e2d-4b95-a697-c739ea2dc5bb) #### Self managed PLATINUM ![self_managed_platinum_after](https://github.com/user-attachments/assets/d7c49551-a8cf-4afb-b3bf-c3243e892219) #### Self managed TRIAL ![self_managed_trial_after](https://github.com/user-attachments/assets/d5cc03a9-97aa-4c78-a5f5-92e5af3a85ac) #### Self managed ENTERPRISE ![self_managed_enterprise_after](https://github.com/user-attachments/assets/a849b534-7e07-4481-9641-c48dee126466) #### Serverless ESSENTIALS ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) #### Serverless COMPLETE ![serverless_complete_after](https://github.com/user-attachments/assets/8cab60c3-dea6-4d7a-b86a-b2cd11c9b4dd) ## Desk Testing ### Severless: Desk testing (just) the upgrade CTA Reproduction steps: 1) Comment-out any preconfigured connectors in `config/kibana.dev.yml` 2) Edit the configuration of `config/serverless.security.yml` to enable the `essentials` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' } ] ``` 3) Start Elasticsearch ```sh yarn es serverless --projectType security ``` 4) Start a development instance of Kibana ``` yarn start --serverless=security --no-base-path ``` 5) Navigate to Security > Attack discovery **Expected result** - An upgrade CTA is displayed, as illustrated by the _after_ screenshot below: ![serverless_essentials_after](https://github.com/user-attachments/assets/4cdd146e-afac-4f3e-925b-4786e1908312) - The video tour is NOT displayed for serverless, as noted in the [original PR](elastic#182605 (comment)) **Actual result** - An upgrade CTA is NOT displayed, as illustrated by the _before_ screenshot below: ![serverless_essentials_before](https://github.com/user-attachments/assets/90e8f433-896d-40a3-b095-8f0cca0f7073) ### Desk testing Self Managed To desk test self manged, we will: 1) Create (three) roles for testing 2) Create (three) users assigned to the roles 3) Test each role at `Basic`, `Trial`, `Platinum`, and `Enterprise` levels to verify: - `Attack discovery` link visibility in the Security solution navigation - Visibility of the upsell empty prompt for license levels where Attack discovery is unavailable - The upsell empty prompt includes the `Subscription plans` and `Manage license` actions - When Attack discoveries are generated, the `View in Ai Assistant` button and popover menu action are enabled / disabled, based on availability of the `AI Assistant` feature #### Creating (three) roles for testing In this section, we will start a new (development) self managed deployment, and create the following three roles via Kibana Dev Tools: - `has_attack_discovery_all_assistant_all` - `has_attack_discovery_all_assistant_none` - `has_attack_discovery_none_assistant_all` To start the deployment and create the roles: 1) Add a pre-configured GenAI connector to `config/kibana.dev.yml` 2) Start a new (development) instance of Elasticsearch: ```sh yarn es snapshot -E path.data=/Users/$USERNAME/data-2024-07-31a ``` 3) Start a local (development) instance of Kibana: ``` yarn start --no-base-path ```` 4) Login to Kibana as the `elastic` user 5) Generate some alerts 6) Navigate to Dev Tools 7) Execute the following three API calls to create the roles: <details><summary>PUT /_security/role/has_attack_discovery_all_assistant_all</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_all_assistant_all { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAssistant.minimal_all", "feature_securitySolutionAttackDiscovery.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> <details><summary>PUT /_security/role/has_attack_discovery_all_assistant_none</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_all_assistant_none { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAttackDiscovery.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> <details><summary>PUT /_security/role/has_attack_discovery_none_assistant_all</summary> <p> ``` ts PUT /_security/role/has_attack_discovery_none_assistant_all { "cluster": [ "all" ], "indices": [ { "names": [ "*" ], "privileges": [ "all" ], "field_security": { "grant": [ "*" ], "except": [] }, "allow_restricted_indices": false } ], "applications": [ { "application": "kibana-.kibana", "privileges": [ "feature_securitySolutionAssistant.minimal_all", "feature_siem.all", "feature_securitySolutionCases.all", "feature_actions.all" ], "resources": [ "*" ] } ], "run_as": [], "metadata": {}, "transient_metadata": { "enabled": true } } ``` </p> </details> #### Creating (three) users assigned to the roles In this section, we will create the following three users via Kibana Dev Tools using the API calls below (expand for details): - `attack_discovery_all_assistant_all` - `attack_discovery_all_assistant_none` - `attack_discovery_none_assistant_all` 1) Navigate to Dev Tools 2) Execute the following three API calls to create the users: <details><summary>POST /_security/user/attack_discovery_all_assistant_all</summary> <p> ``` ts POST /_security/user/attack_discovery_all_assistant_all { "username": "attack_discovery_all_assistant_all", "password": "changeme", "roles": [ "has_attack_discovery_all_assistant_all" ], "full_name": "Attack Discovery All Assistant All", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> <details><summary>POST /_security/user/attack_discovery_all_assistant_none</summary> <p> ``` ts POST /_security/user/attack_discovery_all_assistant_none { "username": "attack_discovery_all_assistant_none", "password": "changeme", "roles": [ "has_attack_discovery_all_assistant_none" ], "full_name": "Attack Discovery All Assistant None", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> <details><summary>POST /_security/user/attack_discovery_none_assistant_all</summary> <p> ``` ts POST /_security/user/attack_discovery_none_assistant_all { "username": "attack_discovery_none_assistant_all", "password": "changeme", "roles": [ "has_attack_discovery_none_assistant_all" ], "full_name": "Attack Discovery None Assistant All", "email": "user@example.com", "metadata": {}, "enabled": true } ``` </p> </details> #### Testing each role at `Basic`, `Trial`, `Platinum`, and `Enterprise` levels In this section, we will test each of the self managed `Basic`, `Trial`, `Platinum`, and `Enterprise` license levels with the three roles we created for testing. ##### Testing the `has_attack_discovery_all_assistant_all` role 1) Login as the `attack_discovery_all_assistant_all` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_all` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_all` | Trial | ✅ | ❌ | ❌ | ✅ | | `has_attack_discovery_all_assistant_all` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_all` | Enterprise | ✅ | ❌ | ❌ | ✅ | ##### Testing the `has_attack_discovery_all_assistant_none` role 1) Login as the `attack_discovery_all_assistant_none` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_all_assistant_none` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Trial | ✅ | ❌ | ❌ | ❌ | | `has_attack_discovery_all_assistant_none` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_all_assistant_none` | Enterprise | ✅ | ❌ | ❌ | ❌ | ##### Testing the `has_attack_discovery_none_assistant_all` role 1) Login as the `attack_discovery_none_assistant_all` user 2) Navigate to the Security solution 3) For each of the `Basic`, `Trial`, `Platinum`, and `Enterprise` levels, verify your observations match the expected behavior in the table below: | Role | License | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `has_attack_discovery_none_assistant_all` | Basic | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_none_assistant_all` | Trial | ❌ | ❌ | ❌ | ❌ | | `has_attack_discovery_none_assistant_all` | Platinum | ✅ | ✅ | ✅ | ❌ | | `has_attack_discovery_none_assistant_all` | Enterprise | ❌ | ❌ | ❌ | ❌ | --------------------------------------------- ### Serverless Testing To desk test serverless, we will test the `essentials` and `complete` product tiers to verify: - `Attack discovery` link visibility in the Security project navigation - Visibility of the upsell empty prompt for license levels where Attack discovery is unavailable - The upsell empty prompt does NOT include the `Subscription plans` and `Manage license` actions - When Attack discoveries are generated, the `View in Ai Assistant` button and popover menu action are enabled #### Essentials tier testing 1) Add a pre-configured GenAI connector to `config/kibana.dev.yml` 2) Edit the configuration of `config/serverless.security.yml` to enable the `essentials` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'essentials' }, { product_line: 'endpoint', product_tier: 'essentials' }, ] ``` 2) Start a new (development) instance of Elasticsearch: ```sh yarn es serverless --clean --projectType security ``` 3) Start a local (development) instance of Kibana: ``` yarn start --serverless=security --no-base-path ```` 4) select the `admin` role 5) Generate some alerts 6) Verify your observations match the expected behavior in the table below: | Role | Tier | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------|------------|--------------------|-------------|--------------------|---------------------------| | `viewer` | essentials | ✅ | ✅ | ❌ | ❌ | | `editor` | essentials | ✅ | ✅ | ❌ | ❌ | | `t1_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `t2_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `t3_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `threat_intelligence_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `rule_author` | essentials | ✅ | ✅ | ❌ | ❌ | | `soc_manager` | essentials | ✅ | ✅ | ❌ | ❌ | | `detections_admin` | essentials | ✅ | ✅ | ❌ | ❌ | | `platform_engineer` | essentials | ✅ | ✅ | ❌ | ❌ | | `endpoint_operations_analyst` | essentials | ✅ | ✅ | ❌ | ❌ | | `endpoint_policy_manager` | essentials | ✅ | ✅ | ❌ | ❌ | | `admin` | essentials | ✅ | ✅ | ❌ | ❌ | | `system_indices_superuser` | essentials | ✅ | ✅ | ❌ | ❌ | ### Complete tier testing 1) Stop the running Kibana server (from the previous Essentials tier testing) 2) Edit the configuration of `config/serverless.security.yml` to enable the `complete` product tier: ```yaml xpack.securitySolutionServerless.productTypes: [ { product_line: 'security', product_tier: 'complete' }, { product_line: 'endpoint', product_tier: 'complete' }, ] ``` 3) Restart a local (development) instance of Kibana: ``` yarn start --serverless=security --no-base-path ```` 4) Verify your observations match the expected behavior in the table below: | Role | Tier | Navigation visible | Show upsell | Upsell has actions | View in assistant enabled | |-------------------------------|----------|--------------------|-------------|--------------------|---------------------------| | `viewer` | complete | ✅ | ❌ | ❌ | ✅ | | `editor` | complete | ✅ | ❌ | ❌ | ✅ | | `t1_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `t2_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `t3_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `threat_intelligence_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `rule_author` | complete | ✅ | ❌ | ❌ | ✅ | | `soc_manager` | complete | ✅ | ❌ | ❌ | ✅ | | `detections_admin` | complete | ✅ | ❌ | ❌ | ✅ | | `platform_engineer` | complete | ✅ | ❌ | ❌ | ✅ | | `endpoint_operations_analyst` | complete | ✅ | ❌ | ❌ | ✅ | | `endpoint_policy_manager` | complete | ✅ | ❌ | ❌ | ✅ | | `admin` | complete | ✅ | ❌ | ❌ | ✅ | | `system_indices_superuser` | complete | ✅ | ❌ | ❌ | ✅ |
Summary
ad.mov
The Attack discovery tour is a 2 step tour.
EuiTourStep
anchored to the nav. The tour component needs an anchor to mount to. Therefore, the nav needs to mount before the tour step. I added anonMount
method tosolution_side_nav.tsx
and I wait for the nav to mount before mounting theAttackDiscoveryTour
component. When the user clicks "Try it", the page redirects to Attack discovery and step 2 is activated. When the user clicks "Close" step 2 is activated but the page does not redirect. This way, when the user navigates on their own to Attack discovery, the video toast is up and ready.EuiToast
containing an overview video. Currently, we cannot make video full screen due to this core CSP issue. Therefore, we decided to open the video in a new tab to play. The video autoplays on mute. I added some fun event listeners to enable anonClick
event on the iframe. When the iframe is clicked, the video opens in a new tab. When the "Watch overview video" button is clicked, the video opens in a new tab. When the user closes the toast, the tour ends.Things to note
main
. Here is the issue to remove the tour for 8.16 [Task] Remove Attack discovery tour in 8.16 #182855Testing
securitySolution.attackDiscovery.newFeaturesTour.v8.14
Explore reviewer
Because the
EuiTourStep
needs the anchor to mount first, I added anonMount
method tosolution_side_nav.tsx
. I wait to mount the tour until the side nav has mounted. I also added anid
to the nav item as this is required to use as an anchor withEuiTourStep